/**
 * 公式选择题生成器
 */
import QuestionGeneratorBase from './question-generator-base.js';

class SpeedFormulaChoiceGenerator extends QuestionGeneratorBase {
    /**
     * 格式化数字以用于公式代入（避免产生双重符号）
     * @param {number} num 数字
     * @returns {string} 格式化后的字符串
     */
    static formatNumberForSubstitution(num) {
        // 四舍五入到4位小数
        const rounded = parseFloat(num.toFixed(4));
        const str = rounded.toString();

        // 如果是负数，返回带括号的形式，这样在字符串插入时不会产生 +- 或 -+
        if (rounded < 0) {
            // 返回括号形式：(-0.4243) 而不是 -0.4243
            return `(${str})`;
        }
        return str;
    }

    /**
     * 格式化带入数值的公式表达式，使其更易读
     * @param {string} formula 原始公式字符串
     * @returns {string} 格式化后的公式字符串
     */
    static formatSubstitutedFormula(formula) {
        let formatted = formula;

        // 处理双重符号：+- 或 -+ -> 单个符号
        formatted = formatted.replace(/\+\-/g, '-');
        formatted = formatted.replace(/\-\+/g, '-');

        // 移除符号后的前导零：1-00.4243 -> 1-0.4243, 1+00.4763 -> 1+0.4763
        formatted = formatted.replace(/([+\-])0+(\d+\.\d+)/g, '$1$2');

        // 去除整数部分的多个前导零（纯整数，不是小数）
        formatted = formatted.replace(/([+\-*/()= ])0+(\d+)(?![.])/g, '$1$2');

        // 处理末尾的 .0（整数）
        formatted = formatted.replace(/\.0\b/g, '');

        // 对于小于1的小数，确保前面有0（如果前面没有符号）
        formatted = formatted.replace(/([+\-*/()= ])\.(\d+)/g, '$10.$2');

        // 格式化多位小数，保留合理的小数位数
        formatted = formatted.replace(/(\d+\.\d{5,})/g, (match) => {
            return parseFloat(match).toFixed(4).replace(/\.?0+$/, '');
        });

        return formatted;
    }

    /**
     * 将数学公式转换为 LaTeX 格式
     * @param {string} formula 数学公式字符串
     * @returns {string} LaTeX 格式的公式
     */
    static convertToLatex(formula) {
        // 如果为空，返回空
        if (!formula) return '';

        let latex = formula.toString();
        
        // 先处理括号内的负数，避免被误处理
        // 例如: 1+(-0.4243) -> 1+(-0.4243)
        latex = latex.replace(/\((-?\d+\.?\d*)\)/g, '($1)');

        // 移除所有空格
        latex = latex.replace(/\s+/g, '');

        // 转换乘号 - 使用 \cdot
        latex = latex.replace(/\*/g, ' \\cdot ');

        // 转换除号 - 使用 \div
        latex = latex.replace(/\//g, ' \\div ');

        // 清理多余空格
        latex = latex.replace(/\s+/g, ' ').trim();

        return latex;
    }

    /**
     * 生成公式选择题
     * @param {Object} options 选项配置
     * @returns {Array} 题目数组
     */
    static generateQuestions(options = {}) {
        const {
            count = 10, formulas = ['formula1', 'formula2'], optionsCount = 4
        } = options;

        const questions = [];

        for (let i = 0; i < count; i++) {
            // 随机选择一个公式类型
            const formulaType = formulas[Math.floor(Math.random() * formulas.length)];

            // 生成基于公式的题目
            const questionData = this.generateFormulaQuestion(formulaType);

            // 生成选项（包含正确答案和干扰项）
            const optionsSet = new Set([this.formatAnswerForChoice(questionData.correctAnswer, 'decimal')]);

            // 判断正确答案是否为负数
            const isCorrectAnswerNegative = questionData.correctAnswer < 0;

            // 生成干扰项
            let distractorAttempts = 0;
            const maxDistractorAttempts = 50; // 防止无限循环

            while (optionsSet.size < optionsCount && distractorAttempts < maxDistractorAttempts) {
                distractorAttempts++;

                // 生成干扰项：在正确答案附近生成
                const offset = (Math.random() - 0.5) * Math.abs(questionData.correctAnswer) * 0.5;
                let distractor = questionData.correctAnswer + offset;

                // 如果正确答案是负数，确保干扰项也是负数
                if (isCorrectAnswerNegative) {
                    if (distractor >= 0) {
                        // 如果计算出的干扰项是正数，转换为负数
                        distractor = -Math.abs(distractor);
                    }
                } else {
                    // 如果正确答案是正数，确保干扰项也是正数
                    if (distractor < 0) {
                        distractor = Math.abs(distractor);
                    }
                }

                // 四舍五入到2位小数
                distractor = this.roundToDecimalPlaces(distractor, 2);

                const formattedDistractor = this.formatAnswerForChoice(distractor, 'decimal');

                // 确保干扰项不重复且与正确答案不同
                const correctAnswerFormatted = this.formatAnswerForChoice(questionData.correctAnswer, 'decimal');
                if (!optionsSet.has(formattedDistractor) && formattedDistractor !== correctAnswerFormatted) {
                    optionsSet.add(formattedDistractor);
                }
            }

            // 打乱选项顺序
            const optionsArray = Array.from(optionsSet);
            const shuffledOptions = this.shuffleArray(optionsArray);
            const correctIndex = shuffledOptions.indexOf(this.formatAnswerForChoice(questionData.correctAnswer, 'decimal'));

            // 生成 LaTeX 公式
            const latexFormula = this.convertToLatex(questionData.substitutedFormula);
            console.log('latexFormula: ' + latexFormula)

            questions.push({
                id: `formula_choice_${Date.now()}_${i}`,
                formulaName: questionData.formulaName,
                question: questionData.question,
                questionParts: questionData.questionParts,
                substitutedFormula: questionData.substitutedFormula,
                latexFormula: latexFormula,
                correctAnswer: this.formatAnswerForChoice(questionData.correctAnswer, 'decimal'),
                options: shuffledOptions,
                correctIndex: correctIndex,
                userAnswer: null,
                isCorrect: null,
                timeUsed: 0
            });
        }

        return questions;
    }

    /**
     * 生成基于公式的题目
     * @param {string} formulaType 公式类型
     * @returns {Object} 题目数据
     */
    static generateFormulaQuestion(formulaType) {
        // 生成随机参数
        const params = this.generateFormulaParams();

        switch (formulaType) {
            case 'formula1': // 求基期量：A/(1+a)
                return this.generateBasePeriodQuestion(params);
            case 'formula2': // 求增长率：(A-B)/B
                return this.generateGrowthRateQuestion(params);
            case 'formula3': // 求基期比重：A/B*(1+b)/(1+a)
                return this.generateBasePeriodProportionQuestion(params);
            case 'formula4': // 求两期比重差：A/B*(a-b)/(1+a)
                return this.generateTwoPeriodProportionDifferenceQuestion(params);
            case 'formula5': // 根据年均增长求现期量：A*(1+r)^n
                return this.generateAverageGrowthQuestion(params);
            default:
                // 默认使用求基期量公式
                return this.generateBasePeriodQuestion(params);
        }
    }

    /**
     * 生成公式参数
     * @returns {Object} 参数对象
     */
    static generateFormulaParams() {
        // 生成合理的参数值
        // 对于增长率题目，允许A < B以产生负增长率，增加难度
        const A = this.roundToDecimalPlaces(Math.random() * 9999 + 1, 2); // 1-10000之间的数
        const B = this.roundToDecimalPlaces(Math.random() * 9999 + 1, 2); // 1-10000之间的数

        // 允许负增长率（-50% 到 50%）
        const a = this.roundToDecimalPlaces((Math.random() * 1 - 0.5) + (Math.random() > 0.5 ? 0.01 : -0.01), 4);
        const b = this.roundToDecimalPlaces((Math.random() * 1 - 0.5) + (Math.random() > 0.5 ? 0.01 : -0.01), 4);

        const r = this.roundToDecimalPlaces(Math.random() * 0.3 + 0.01, 4); // 1%-30%的年均增长率
        const n = Math.floor(Math.random() * 10) + 1; // 1-10年的年数

        return {A, B, a, b, r, n};
    }

    /**
     * 生成基期量题目：A/(1+a)
     * @param {Object} params 参数
     * @returns {Object} 题目数据
     */
    static generateBasePeriodQuestion(params) {
        const {A, a} = params;
        const correctAnswer = A / (1 + a);
        const substitutedFormula = `${this.formatNumber(A)}/(1+${this.formatNumberForSubstitution(a)})`;
        const formulaExpression = 'A/(1+a)';

        // 格式化显示的增长率（百分数），处理负数
        const displayA = this.formatNumber(A);
        const displayA_percent = this.formatNumber(a * 100) + '%';

        // 格式化代入数值的公式
        const formattedSubstituted = this.formatSubstitutedFormula(substitutedFormula);

        // 构建结构化题目部分: [text, value, text, value, text, formula, text, substituted, text]
        const questionParts = ['现期量A=', {type: 'value', value: displayA}, '，增长率a=', {
            type: 'value',
            value: displayA_percent
        }, '，基期量=', {type: 'formula', value: formulaExpression}, '=', {
            type: 'substituted',
            value: formattedSubstituted
        }, '=?'];

        return {
            formulaName: '求基期量',
            question: `现期量A=${A}，增长率a=${(a * 100).toFixed(2)}%，基期量=A/(1+a)`,
            questionParts: questionParts,
            substitutedFormula: substitutedFormula,
            correctAnswer: this.roundToDecimalPlaces(correctAnswer, 2)
        };
    }

    /**
     * 生成增长率题目：(A-B)/B
     * @param {Object} params 参数
     * @returns {Object} 题目数据
     */
    static generateGrowthRateQuestion(params) {
        const {A, B} = params;
        const correctAnswer = (A - B) / B;
        const substitutedFormula = `(${A}-${B})/${B}`;
        const formulaExpression = '(A-B)/B';

        const displayA = this.formatNumber(A);
        const displayB = this.formatNumber(B);

        // 格式化代入数值的公式
        const formattedSubstituted = this.formatSubstitutedFormula(substitutedFormula);

        const questionParts = ['现期量A=', {type: 'value', value: displayA}, '，基期量B=', {
            type: 'value',
            value: displayB
        }, '，增长率=', {type: 'formula', value: formulaExpression}, '=', {
            type: 'substituted',
            value: formattedSubstituted
        }, '=?'];

        return {
            formulaName: '求增长率',
            question: `现期量A=${A}，基期量B=${B}，增长率=(A-B)/B`,
            questionParts: questionParts,
            substitutedFormula: substitutedFormula,
            correctAnswer: this.roundToDecimalPlaces(correctAnswer, 4)
        };
    }

    /**
     * 生成基期比重题目：A/B*(1+b)/(1+a)
     * @param {Object} params 参数
     * @returns {Object} 题目数据
     */
    static generateBasePeriodProportionQuestion(params) {
        const {A, B, a, b} = params;
        const correctAnswer = (A / B) * ((1 + b) / (1 + a));
        // 使用格式化的数字以避免产生双重符号
        const substitutedFormula = `${this.formatNumber(A)}/${this.formatNumber(B)}*(1+${this.formatNumberForSubstitution(b)})/(1+${this.formatNumberForSubstitution(a)})`;
        const formulaExpression = 'A/B*(1+b)/(1+a)';

        const displayA = this.formatNumber(A);
        const displayB = this.formatNumber(B);
        const displayA_percent = this.formatNumber(a * 100) + '%';
        const displayB_percent = this.formatNumber(b * 100) + '%';

        // 格式化代入数值的公式
        const formattedSubstituted = this.formatSubstitutedFormula(substitutedFormula);

        const questionParts = ['现期分量A=', {type: 'value', value: displayA}, '，现期总量B=', {
            type: 'value',
            value: displayB
        }, '，分量增长率a=', {type: 'value', value: displayA_percent}, '，总量增长率b=', {
            type: 'value',
            value: displayB_percent
        }, '，基期比重=', {type: 'formula', value: formulaExpression}, '=', {
            type: 'substituted',
            value: formattedSubstituted
        }, '=?'];

        return {
            formulaName: '求基期比重',
            question: `现期分量A=${A}，现期总量B=${B}，分量增长率a=${(a * 100).toFixed(2)}%，总量增长率b=${(b * 100).toFixed(2)}%，基期比重=A/B*(1+b)/(1+a)`,
            questionParts: questionParts,
            substitutedFormula: substitutedFormula,
            correctAnswer: this.roundToDecimalPlaces(correctAnswer, 4)
        };
    }

    /**
     * 生成两期比重差题目：A/B*(a-b)/(1+a)
     * @param {Object} params 参数
     * @returns {Object} 题目数据
     */
    static generateTwoPeriodProportionDifferenceQuestion(params) {
        const {A, B, a, b} = params;
        const correctAnswer = (A / B) * ((a - b) / (1 + a));
        const substitutedFormula = `${this.formatNumber(A)}/${this.formatNumber(B)}*(${this.formatNumberForSubstitution(a)}-${this.formatNumberForSubstitution(b)})/(1+${this.formatNumberForSubstitution(a)})`;
        const formulaExpression = 'A/B*(a-b)/(1+a)';

        const displayA = this.formatNumber(A);
        const displayB = this.formatNumber(B);
        const displayA_percent = this.formatNumber(a * 100) + '%';
        const displayB_percent = this.formatNumber(b * 100) + '%';

        // 格式化代入数值的公式
        const formattedSubstituted = this.formatSubstitutedFormula(substitutedFormula);

        const questionParts = ['现期分量A=', {type: 'value', value: displayA}, '，现期总量B=', {
            type: 'value',
            value: displayB
        }, '，分量增长率a=', {type: 'value', value: displayA_percent}, '，总量增长率b=', {
            type: 'value',
            value: displayB_percent
        }, '，两期比重差=', {type: 'formula', value: formulaExpression}, '=', {
            type: 'substituted',
            value: formattedSubstituted
        }, '=?'];

        return {
            formulaName: '求两期比重差',
            question: `现期分量A=${A}，现期总量B=${B}，分量增长率a=${(a * 100).toFixed(2)}%，总量增长率b=${(b * 100).toFixed(2)}%，两期比重差=A/B*(a-b)/(1+a)`,
            questionParts: questionParts,
            substitutedFormula: substitutedFormula,
            correctAnswer: this.roundToDecimalPlaces(correctAnswer, 4)
        };
    }

    /**
     * 生成年均增长题目：A*(1+r)^n
     * @param {Object} params 参数
     * @returns {Object} 题目数据
     */
    static generateAverageGrowthQuestion(params) {
        const {A, r, n} = params;
        const correctAnswer = A * Math.pow(1 + r, n);
        const substitutedFormula = `${this.formatNumber(A)}*(1+${this.formatNumberForSubstitution(r)})^${n}`;
        const formulaExpression = 'A*(1+r)^n';

        const displayA = this.formatNumber(A);
        const displayR_percent = this.formatNumber(r * 100) + '%';
        const displayN = n.toString();

        // 格式化代入数值的公式
        const formattedSubstituted = this.formatSubstitutedFormula(substitutedFormula);

        const questionParts = ['基期量A=', {type: 'value', value: displayA}, '，年均增长率r=', {
            type: 'value',
            value: displayR_percent
        }, '，年数n=', {type: 'value', value: displayN}, '，现期量=', {
            type: 'formula',
            value: formulaExpression
        }, '=', {type: 'substituted', value: formattedSubstituted}, '=?'];

        return {
            formulaName: '根据年均增长求现期量',
            question: `基期量A=${A}，年均增长率r=${(r * 100).toFixed(2)}%，年数n=${n}，现期量=A*(1+r)^n`,
            questionParts: questionParts,
            substitutedFormula: substitutedFormula,
            correctAnswer: this.roundToDecimalPlaces(correctAnswer, 2)
        };
    }
}

export default SpeedFormulaChoiceGenerator;

